"""GUI Main Window - PySide6 Implementation."""

import asyncio
import sys
from uuid import UUID

from PySide6.QtCore import Qt, QThread, QTimer, Signal
from PySide6.QtWidgets import (
    QApplication,
    QHBoxLayout,
    QHeaderView,
    QLabel,
    QLineEdit,
    QMainWindow,
    QMessageBox,
    QPushButton,
    QTableWidget,
    QTableWidgetItem,
    QVBoxLayout,
    QWidget,
)

from ..core.task_manager import TaskManager
from ..models.database import db
from ..models.task import DownloadTask, TaskStatus
from ..utils.logger import setup_logger

logger = setup_logger()


class TaskManagerThread(QThread):
    """Manages the asyncio event loop for the TaskManager in a separate thread."""

    def __init__(self, task_manager: TaskManager):
        """Initializes the TaskManagerThread.

        Args:
            task_manager: The task manager instance to run.
        """
        super().__init__()
        self.task_manager = task_manager
        self.loop: asyncio.AbstractEventLoop | None = None

    def run(self) -> None:
        """Initializes and runs a new asyncio event loop in this thread, starting the TaskManager and then running the loop indefinitely."""
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        # 启动任务管理器
        self.loop.run_until_complete(self.task_manager.start())

        # 运行事件循环
        self.loop.run_forever()

    def stop(self) -> None:
        """Stops the thread and the asyncio loop, ensuring the TaskManager is properly shut down."""
        if self.loop:
            asyncio.run_coroutine_threadsafe(self.task_manager.stop(), self.loop)
            self.loop.call_soon_threadsafe(self.loop.stop)


class MainWindow(QMainWindow):
    """Main application window for SwiftShadow, providing a GUI for managing download tasks."""

    # 信号定义
    task_updated = Signal(UUID, TaskStatus)

    def __init__(self) -> None:
        """Initializes the main window, sets up the UI components, and starts the task manager."""
        super().__init__()

        self.task_manager = TaskManager()
        self.task_manager_thread: TaskManagerThread | None = None
        self.tasks_cache: dict[UUID, DownloadTask] = {}

        self.init_ui()
        self.start_task_manager()

        # 定时刷新任务列表
        self.refresh_timer = QTimer()
        self.refresh_timer.timeout.connect(self.refresh_task_list)
        self.refresh_timer.start(1000)  # 每秒刷新

    def init_ui(self) -> None:
        """Initializes the user interface components of the main window, including input fields, buttons, and task table."""
        self.setWindowTitle("疾影下载器 - SwiftShadow")
        self.setGeometry(100, 100, 1000, 600)

        # 中央Widget
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # 主布局
        main_layout = QVBoxLayout()
        central_widget.setLayout(main_layout)

        # === 顶部:添加任务区域 ===
        add_task_layout = QHBoxLayout()

        self.url_input = QLineEdit()
        self.url_input.setPlaceholderText("输入下载URL...")
        self.url_input.returnPressed.connect(self.add_task)
        add_task_layout.addWidget(self.url_input)

        add_button = QPushButton("添加任务")
        add_button.clicked.connect(self.add_task)
        add_task_layout.addWidget(add_button)

        main_layout.addLayout(add_task_layout)

        # === 中部:任务列表 ===
        self.task_table = QTableWidget()
        self.task_table.setColumnCount(6)
        self.task_table.setHorizontalHeaderLabels(["标题", "状态", "进度", "速度", "大小", "操作"])

        # 自动调整列宽
        header = self.task_table.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)  # 标题列自动拉伸
        header.setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(3, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(4, QHeaderView.ResizeMode.ResizeToContents)
        header.setSectionResizeMode(5, QHeaderView.ResizeMode.ResizeToContents)

        main_layout.addWidget(self.task_table)

        # === 底部:状态栏 ===
        self.status_label = QLabel("就绪")
        main_layout.addWidget(self.status_label)

    def start_task_manager(self) -> None:
        """Initializes the database and starts the task manager in a separate thread."""
        # 在后台线程初始化数据库
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(db.initialize())

        # 启动任务管理器线程
        self.task_manager_thread = TaskManagerThread(self.task_manager)
        self.task_manager_thread.start()

        self.status_label.setText("任务管理器已启动")
        logger.info("GUI任务管理器已启动")

    def add_task(self) -> None:
        """Adds a new download task based on the URL input from the UI.

        If the URL input is empty, a warning message box is displayed.
        The task is added in a separate thread to avoid blocking the UI.
        """
        url = self.url_input.text().strip()

        if not url:
            QMessageBox.warning(self, "错误", "请输入有效的URL")
            return

        self.status_label.setText(f"正在添加任务: {url}")

        # 在后台线程添加任务
        def _add():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)

            task = DownloadTask(
                url=url,
                title="获取中...",
                filename=f"download_{len(self.tasks_cache)}.mp4",
                save_path=f"./downloads/download_{len(self.tasks_cache)}.mp4",
            )

            task_id = loop.run_until_complete(self.task_manager.add_task(task))
            self.tasks_cache[task_id] = task

            # 清空输入框
            self.url_input.clear()
            self.status_label.setText(f"任务已添加: {task.title}")

        # 使用QThread避免阻塞UI
        from threading import Thread

        thread = Thread(target=_add)
        thread.start()

    def refresh_task_list(self) -> None:
        """Refreshes the list of tasks displayed in the table by fetching updated task information from the TaskManager."""

        def _refresh():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)

            tasks = loop.run_until_complete(self.task_manager.list_tasks(limit=100))

            # 更新缓存
            for task in tasks:
                self.tasks_cache[task.id] = task

            # 在主线程更新UI
            self.update_task_table(tasks)

        # 后台刷新
        from threading import Thread

        thread = Thread(target=_refresh)
        thread.start()

    def update_task_table(self, tasks: list[DownloadTask]) -> None:
        """Updates the task table with the given list of download tasks.

        Args:
            tasks: A list of DownloadTask objects to display.
        """
        self.task_table.setRowCount(len(tasks))

        for row, task in enumerate(tasks):
            # 标题
            self.task_table.setItem(row, 0, QTableWidgetItem(task.title))

            # 状态
            status_item = QTableWidgetItem(task.status.value)
            status_color = {
                TaskStatus.PENDING: Qt.GlobalColor.yellow,
                TaskStatus.DOWNLOADING: Qt.GlobalColor.blue,
                TaskStatus.PAUSED: Qt.GlobalColor.cyan,
                TaskStatus.COMPLETED: Qt.GlobalColor.green,
                TaskStatus.FAILED: Qt.GlobalColor.red,
            }.get(task.status, Qt.GlobalColor.white)
            status_item.setForeground(status_color)
            self.task_table.setItem(row, 1, status_item)

            # 进度
            progress_text = f"{task.progress:.1f}%"
            self.task_table.setItem(row, 2, QTableWidgetItem(progress_text))

            # 速度
            speed_mb = task.speed / 1024 / 1024 if task.speed else 0
            speed_text = f"{speed_mb:.2f} MB/s" if speed_mb > 0 else "-"
            self.task_table.setItem(row, 3, QTableWidgetItem(speed_text))

            # 大小
            size_text = self.format_size(task.file_size) if task.file_size else "未知"
            self.task_table.setItem(row, 4, QTableWidgetItem(size_text))

            # 操作按钮
            action_widget = QWidget()
            action_layout = QHBoxLayout()
            action_layout.setContentsMargins(0, 0, 0, 0)

            if task.status == TaskStatus.DOWNLOADING:
                pause_btn = QPushButton("暂停")
                pause_btn.clicked.connect(lambda checked, t=task: self.pause_task(t.id))
                action_layout.addWidget(pause_btn)
            elif task.status in (TaskStatus.PAUSED, TaskStatus.FAILED):
                resume_btn = QPushButton("恢复")
                resume_btn.clicked.connect(lambda checked, t=task: self.resume_task(t.id))
                action_layout.addWidget(resume_btn)

            delete_btn = QPushButton("删除")
            delete_btn.clicked.connect(lambda checked, t=task: self.delete_task(t.id))
            action_layout.addWidget(delete_btn)

            action_widget.setLayout(action_layout)
            self.task_table.setCellWidget(row, 5, action_widget)

    def pause_task(self, task_id: UUID) -> None:
        """Pauses a specific download task.

        Args:
            task_id: The unique identifier of the task to pause.
        """

        def _pause():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            loop.run_until_complete(self.task_manager.pause_task(task_id))
            self.status_label.setText(f"任务已暂停: {task_id}")

        from threading import Thread

        Thread(target=_pause).start()

    def resume_task(self, task_id: UUID) -> None:
        """Resumes a paused download task.

        Args:
            task_id: The unique identifier of the task to resume.
        """

        def _resume():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            loop.run_until_complete(self.task_manager.resume_task(task_id))
            self.status_label.setText(f"任务已恢复: {task_id}")

        from threading import Thread

        Thread(target=_resume).start()

    def delete_task(self, task_id: UUID) -> None:
        """Deletes a specific download task after user confirmation.

        Args:
            task_id: The unique identifier of the task to delete.
        """
        reply = QMessageBox.question(
            self,
            "确认删除",
            "确定要删除这个任务吗?",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
        )

        if reply == QMessageBox.StandardButton.Yes:
            def _delete():
                loop = asyncio.new_event_loop()
                asyncio.set_event_loop(loop)
                loop.run_until_complete(self.task_manager.delete_task(task_id))
                self.tasks_cache.pop(task_id, None)
                self.status_label.setText(f"任务已删除: {task_id}")

            from threading import Thread

            Thread(target=_delete).start()

    @staticmethod
    def format_size(bytes_size: int) -> str:
        """Formats a given size in bytes into a human-readable string.

        Args:
            bytes_size (int): The size in bytes.

        Returns:
            str: A human-readable string representing the size (e.g., "1.23 MB").
        """
        for unit in ["B", "KB", "MB", "GB", "TB"]:
            if bytes_size < 1024:
                return f"{bytes_size:.2f} {unit}"
            bytes_size /= 1024
        return f"{bytes_size:.2f} PB"

    def show_settings(self) -> None:
        """Displays the application settings dialog."""

    def closeEvent(self, event) -> None:
        """Handles the close event of the main window, ensuring the TaskManager thread is properly stopped.

        Args:
            event: The close event.
        """
        if self.task_manager_thread:
            self.task_manager_thread.stop()
            self.task_manager_thread.wait()

        event.accept()


def launch() -> None:
    """Launches the SwiftShadow GUI application."""
    setup_logger()

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())


if __name__ == "__main__":
    launch()
